#include <iostream>

#include "app.hpp"
#include "cv_common.hpp"
#include "cv_face_detector.hpp"
#include "hik_camera.hpp"
#include "timer.hpp"

namespace {

const std::string cascade_name =
    "../../../../data/haarcascade_frontalface_alt.xml";
const std::string eye_cascade_name =
    "../../../../data/haarcascade_eye_tree_eyeglasses.xml";
const std::string nose_cascade_name =
    "../../../../data/haarcascade_mcs_nose.xml";

}  // namespace

class MaskDetector : private App {
 private:
  HikCamera cam_;
  CVFaceDetector detector_;
  bool debug_;

  component::Recorder recorder_ = component::Recorder("DetectionThread");

 public:
  MaskDetector(const std::string log_path) : App(log_path) {
    SPDLOG_WARN("***** Setting Up System. *****");
    debug_ = true;
    cam_.Open(0);
    cam_.Setup(640, 480);
    detector_.ConfigModel(component::DetectModel::kMODEL_EYE |
                          ~component::DetectModel::kMODEL_NOSE |
                          component::DetectModel::kMODEL_FACE);
    detector_.LoadParams(cascade_name, eye_cascade_name, nose_cascade_name);
  }

  ~MaskDetector() { SPDLOG_WARN("***** Shuted Down System. *****"); }

  void Run() {
    SPDLOG_WARN("******* Running. ********");
    cv::Mat frame, dest, hue;
    std::vector<cv::Rect2i> faces;

    cv::namedWindow("skin");
    cv::createTrackbar("Hmin", "skin", 0, 90, 0);
    cv::createTrackbar("Hmax", "skin", 0, 90, 0);
    while (1) {
      cam_.GetFrame(frame);
      if (frame.empty()) continue;

      if (debug_) {
        auto err = detector_.Detect(frame);
        if (err == Error::kOK) {
          detector_.VisualizeResult(frame, false);
        }
      } else {
        cv::GaussianBlur(frame, frame, cv::Size(5, 5), 0);
        cv::cvtColor(frame, dest, cv::COLOR_BGR2HSV);
        std::vector<cv::Mat> channels;
        cv::split(dest, channels);
        auto Hmin = cv::getTrackbarPos("Hmin", "skin");
        auto Hmax = cv::getTrackbarPos("Hmax", "skin");
        cv::inRange(channels[0], Hmin, Hmax, hue);
        cv::imshow("HSV", hue);
      }

      cv::imshow("show", frame);
      if (' ' == cv::waitKey(10)) {
        cv::waitKey(0);
      }

      recorder_.Record();
    }
  }
};

int main(int argc, char const* argv[]) {
  (void)argc;
  (void)argv;

  MaskDetector mask("logs/mask.log");
  mask.Run();

  return EXIT_SUCCESS;
}
